﻿using System.ComponentModel;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;

namespace Borg.Framework
{
    public class Bar : Control
    {
        private Color _barBackColor = Color.Green;
        private int _height = 4;
        private int _hspacing = 3;
        private float _value = 0.66f;
        private int _vspacing = 2;

        protected override void OnPaint(PaintEventArgs e)
        {
            var clientRectangle = ClientRectangle;

            clientRectangle.Offset(Padding.Left, Padding.Top);
            clientRectangle.Width -= Padding.Horizontal;
            clientRectangle.Height -= Padding.Vertical;

            using (Brush hatchBrush = new HatchBrush(HatchStyle.Percent50, _barBackColor, BackColor))
            {
                using (Brush solidBrush = new SolidBrush(ForeColor))
                {
                    var rect = new Rectangle(
                        clientRectangle.Left,
                        clientRectangle.Bottom - BarHeight,
                        clientRectangle.Width, BarHeight);

                    var sz = (1f - Value) * clientRectangle.Height + clientRectangle.Top;
                    
                    while (rect.Bottom >= clientRectangle.Top)
                    {
                        if (rect.Top < clientRectangle.Top)
                            rect = new Rectangle(
                                clientRectangle.Top,
                                clientRectangle.Left,
                                clientRectangle.Width,
                                rect.Bottom - clientRectangle.Top);

                        if (rect.Bottom > sz)
                            e.Graphics.FillRectangle(solidBrush, rect);

                        if (sz >= rect.Top && sz <= rect.Bottom)
                        {
                            var rectangle = rect;
                            rectangle.Height = ((int)sz) - rect.Top;
                            e.Graphics.FillRectangle(hatchBrush, rectangle);
                        }

                        if (rect.Bottom < sz)
                            e.Graphics.FillRectangle(hatchBrush, rect);

                        rect.Offset(0, -(BarHeight + VerticalSpacing));
                    }
                }
            }

            if (HorizontalSpacing <= 0)
                return;

            using (Brush solidBrush = new SolidBrush(BackColor))
            {
                var sz = clientRectangle.Location.X + clientRectangle.Width / 2;

                e.Graphics.FillRectangle(
                    solidBrush,
                    sz - HorizontalSpacing / 2,
                    clientRectangle.Top,
                    HorizontalSpacing,
                    clientRectangle.Height);
            }
        }

        [Description("Background color of bar items")]
        [DisplayName("BarBackColor")]
        [Category("Appearance")]
        [DefaultValue(typeof(Color), "Green")]
        public Color BarBackColor
        {
            get { return _barBackColor; }
            set
            {
                _barBackColor = value;
                Invalidate();
            }
        }

        [Description("Height of bar items")]
        [DefaultValue(4)]
        [DisplayName("BarHeight")]
        [Category("Appearance")]
        public int BarHeight
        {
            get { return _height; }
            set
            {
                _height = value;
                Invalidate();
            }
        }

        [DisplayName("HorizontalSpacing")]
        [DefaultValue(3)]
        [Category("Appearance")]
        [Description("Horizontal separator between bar rows")]
        public int HorizontalSpacing
        {
            get { return _hspacing; }
            set
            {
                _hspacing = value;
                Invalidate();
            }
        }

        [DisplayName("Value")]
        [Description("Value to be displayed in bar items")]
        [Category("Data")]
        [DefaultValue(0.66f)]
        public float Value
        {
            get { return _value; }
            set
            {
                _value = value;
                Invalidate();
            }
        }

        [Category("Appearance")]
        [DefaultValue(2)]
        [DisplayName("VerticalSpacing")]
        [Description("Vertical space between bars")]
        public int VerticalSpacing
        {
            get { return _vspacing; }
            set
            {
                _vspacing = value;
                Invalidate();
            }
        }
    }
}

